module MultiplicationDivisionUnit(
	
	input			i_MDU_clk,
	input			i_MDU_enable,
	input			i_MDU_reset,
	
	input	[4:0]	i_MDU_mdcode,
	input	[31:0]	i_MDU_operand1,
	input	[31:0]	i_MDU_operand2,
	input	[63:0]	i_MDU_HILOdata,
	
	output			o_MDU_stall,
	output	[63:0]	o_MDU_result
	
);
	
	wire	[31:0]	op1 = i_MDU_operand1;
	wire	[31:0]	op2 = i_MDU_operand2;
	wire	signed	[31:0]	sop1 = i_MDU_operand1;
	wire	signed	[31:0]	sop2 = i_MDU_operand2;
	
	wire	[63:0]	result_mult_sign;
	wire	[63:0]	result_mult_unsign;
	wire	[63:0]	result_div_sign;
	wire	[63:0]	result_div_unsign;
	
	wire	[63:0]	result_ms = (i_MDU_mdcode==5'd1) ? result_mult_sign 	: 64'd0;
	wire	[63:0]	result_mu = (i_MDU_mdcode==5'd2) ? result_mult_unsign 	: 64'd0;
	wire	[63:0]	result_ds = (i_MDU_mdcode==5'd3) ? result_div_sign 		: 64'd0;
	wire	[63:0]	result_du = (i_MDU_mdcode==5'd4) ? result_div_unsign 	: 64'd0;
	assign	o_MDU_result = result_ms | result_mu | result_ds | result_du;
	
	wire		done_div_sign;
	wire		done_div_unsign;
	
mult_gen_sign MDU_mult_sign(
	.CLK(			i_MDU_clk),
	.A(				sop1),
	.B(				sop2),
	.P(				result_mult_sign),
	.SCLR(			(i_MDU_mdcode!=5'd1))//low active
);

mult_gen_unsign MDU_mult_unsign(
	.CLK(			i_MDU_clk),
	.A(				op1),
	.B(				op2),
	.P(				result_mult_unsign),
	.SCLR(			(i_MDU_mdcode!=5'd2))//low active
);

div_gen_sign MDU_div_sign(
	.aclk(						i_MDU_clk),
		
	.s_axis_dividend_tdata(		sop1),
	.s_axis_dividend_tvalid(	(i_MDU_mdcode==5'd3)),
	
	.s_axis_divisor_tdata(		sop2),
	.s_axis_divisor_tvalid(		(i_MDU_mdcode==5'd3)),
	
	.m_axis_dout_tdata(			result_div_sign),
	.m_axis_dout_tvalid(		done_div_sign)
);

div_gen_unsign MDU_div_unsign(
	.aclk(						i_MDU_clk),
		
	.s_axis_dividend_tdata(		op1),
	.s_axis_dividend_tvalid(	(i_MDU_mdcode==5'd4)),
	
	.s_axis_divisor_tdata(		op2),
	.s_axis_divisor_tvalid(		(i_MDU_mdcode==5'd4)),
	
	.m_axis_dout_tdata(			result_div_unsign),
	.m_axis_dout_tvalid(		done_div_unsign)
);

	reg		[7:0]	stall_m;
	reg		[7:0]	stall_d;
	wire	isMULT = i_MDU_mdcode==5'd1 || i_MDU_mdcode==5'd2;
	wire	isDIV  = i_MDU_mdcode==5'd3 || i_MDU_mdcode==5'd4;
	wire	doneDIV= done_div_sign || done_div_unsign;
	
	wire	o_MDU_stall_m = (stall_m==8'd8) ? 1'd0 :isMULT;
	wire	o_MDU_stall_d = (doneDIV) ? 1'd0 :isDIV;
	wire	o_MDU_stall = o_MDU_stall_m || o_MDU_stall_d；
	
always @(posedge i_MDU_clk)
	begin
		if(i_MDU_reset)
			begin
				stall_m	<= 8'd0;
			end
		else if(i_MDU_enable)
			begin
				if(stall_m==8'd8) stall_m <= 8'd0;
				else if(isMULT) stall_m <= stall_m + 8'd1;
			end
		end
	end

endmodule